package top.vains.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.vains.entity.Files;
import top.vains.entity.Result;
import top.vains.enumeration.FileTypeEnum;
import top.vains.exception.CustomerException;
import top.vains.service.IFilesService;
import top.vains.util.JwtUtils;
import top.vains.util.ResultUtils;
import top.vains.util.VideoUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author vains
 * @since 2020-03-10
 */
@Slf4j
@RestController
@RequestMapping("/files")
@Api(tags = "文件接口，包括上传、下载和获取对应用户的文件信息")
public class FilesController {

    @Value("${file.path}")
    private String basePath;

    private final IFilesService filesService;

    @Autowired
    public FilesController(IFilesService filesService) {
        this.filesService = filesService;
    }

    @GetMapping("/getFiles")
    @ApiOperation(value = "获取当前登陆用户所有的文件夹", notes = "获取当前登陆用户所有的文件/文件夹")
    public Result getFiles(HttpServletRequest request) {
        Integer userId = JwtUtils.getUserIdByToken(request);
        List<Files> files = filesService.getByUserId(userId, 0);
        return ResultUtils.success("查询成功！", files);
    }

    @GetMapping("/getAllFiles")
    @ApiOperation(value = "获取当前登陆用户所有的文件/文件夹", notes = "获取当前登陆用户所有的文件/文件夹")
    public Result getAllFiles(HttpServletRequest request) {
        Integer userId = JwtUtils.getUserIdByToken(request);
        List<Files> files = filesService.getByUserId(userId, -1);
        return ResultUtils.success("查询成功！", files);
    }

    @PostMapping("/upload")
    @ApiOperation(value = "上传接口", notes = "所有文件会通过该接口进行上传")
    public Result upload(@RequestParam("file") MultipartFile file, Files files) {
        Assert.notNull(file, "请选择文件");
        // 获取父文件夹路径
        String parentPath = VideoUtils.getParentPath(files.getFileParentId(), filesService, null);
        // 每个用户根据ID分组，对应不同的文件夹
        String filePath = String.format("%s%d/%s", basePath, files.getUserId(), parentPath);
        File folder = new File(filePath);
        // 如果不存在就创建
        if (!folder.exists()) {
            boolean mkdirs = folder.mkdirs();
            if (!mkdirs) {
                throw new CustomerException("文件夹创建失败，请稍后重试");
            }
        }
        String fileName = file.getOriginalFilename();
        //保存文件
        File file1;
        if (fileName != null) {
            file1 = new File(folder, fileName);
            if (file1.exists()) {
                throw new CustomerException("文件已存在！");
            }
            try {
                file.transferTo(file1);
                String[] split = fileName.split("\\.");
                String suffix = split[split.length - 1];
                files.setFileSuffix(suffix);
                files.setFileName(fileName);
                files.setFileLocalPath(parentPath);
                files.setCreateTime(new Date());
                String cover = null;
                // 图片
                if (Objects.equals(files.getType(), FileTypeEnum.IMAGE.getType())) {
                    cover = files.getUserId() + "/" + parentPath + "/" + files.getFileName();
                }
                // 视频
                if (Objects.equals(files.getType(), FileTypeEnum.VIDEO.getType())) {
                    cover = VideoUtils.createVideoCover(file1);
                    cover = cover.replace("\\", "/");
                }
                files.setCover(cover);
                filesService.save(files);
            } catch (Exception e) {
                return ResultUtils.error("上传失败！");
            }
        }
        return ResultUtils.success("上传成功！");
    }

    @GetMapping("/getFilesByType")
    @ApiOperation(value = "根据文件类型获取文件", notes = "需要携带token")
    public Result getFilesByType(Integer type, HttpServletRequest request) {
        Integer userId = JwtUtils.getUserIdByToken(request);
        List<Files> files = filesService.getFilesByType(type, userId);
        return ResultUtils.success("查询成功！", files);
    }

    @PostMapping("/insertFolder")
    @ApiOperation(value = "新建文件夹", notes = "需要携带token")
    public Result insertFolder(@RequestBody Files files, HttpServletRequest request) {
        Integer userId = JwtUtils.getUserIdByToken(request);
        files.setUserId(userId);
        filesService.save(files);
        files.setCreateTime(new Date());
        return ResultUtils.success("添加成功！");
    }

    @DeleteMapping("/deleteFileById/{fileId}")
    @ApiOperation(value = "删除文件/文件夹", notes = "文件ID")
    public Result deleteFileById(@PathVariable("fileId") Integer fileId) {
        Files byId = filesService.getById(fileId);
        Assert.notNull(byId, "文件不存在！请刷新后重试");
        // 如果是文件，则删除本地文件
        if (byId.getFileType() == 1) {
            String filePath = basePath + byId.getCover();
            try {
                Path path1 = Paths.get(filePath);
                // 删除图片
                java.nio.file.Files.delete(path1);
                // 如果是视频，则将封面和视频都删除
                if (byId.getType().equals(FileTypeEnum.VIDEO.getType())) {
                    String path = basePath +
                            byId.getUserId() +
                            "/" +
                            byId.getFileLocalPath() +
                            "/" +
                            byId.getFileName();
                    Path path2 = Paths.get(path);
                    // 删除
                    java.nio.file.Files.delete(path2);
                }
            } catch (IOException e) {
                throw new CustomerException("文件删除失败！");
            }
        }
        filesService.removeById(fileId);
        return ResultUtils.success("删除成功！");
    }

    @GetMapping("/moveFiles/{fileId}/{parentId}")
    @ApiOperation(value = "删除文件/文件夹", notes = "文件ID")
    public Result removeFiles(@PathVariable("fileId") Integer fileId, @PathVariable("parentId") Integer parentId) {
        Files files = filesService.getById(fileId);
        Assert.notNull(files, "文件不存在！请刷新后重试");
        files.setFileParentId(parentId);
        String parentPath = VideoUtils.getParentPath(files.getFileParentId(), filesService, null);
        // 如果是文件， 则移动服务器上的文件
        if (files.getFileType() == 1) {
            String oldPath = basePath +
                    files.getUserId() +
                    "/" +
                    files.getFileLocalPath() +
                    "/" +
                    files.getFileName();
            File oldFile = new File(oldPath);
            String newPath = basePath +
                    files.getUserId() +
                    "/" +
                    parentPath +
                    "/" +
                    files.getFileName();
            File newFile = new File(newPath);
            log.info("文件父路径：{}", newFile.getParent());
            File parentFile = new File(newFile.getParent());
            if (!parentFile.exists()) {
                boolean mkdirs = parentFile.mkdirs();
                if (!mkdirs) {
                    throw new CustomerException("文件移动失败！");
                }
            }
            boolean rename = oldFile.renameTo(newFile);
            if (!rename) {
                throw new CustomerException("文件移动失败！");
            }
        }
        files.setCover(files.getUserId() + "/" + parentPath + "/" + files.getFileName());
        files.setFileLocalPath(parentPath);
        filesService.updateById(files);
        return ResultUtils.success("移动成功！");
    }

}
